home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-21 | 13.2 KB | 484 lines | [TEXT/R*ch] |
- /*
- AEObj_pd.cp
- © Bob Boylan 1996
-
- Revision History
- MacHack 1996 initial creation
- */
- #include "debug.h"
- #include "AEObj_pd.h"
- #include "ComputerAEObj_pd.h"
- #include "ComputerAETE_da.h"
- #include "AppAEObj_pd.h"
- #include "Helpers_ut.h"
- #include "AEBuild.h"
- #include "ProgressProc_hi.h"
- #include "FinderAppAEObj_pd.h"
-
- #include <algo.h>
- #include <sstream>
-
-
- // class statics
- Int_32 AEObj_pd::_TimeoutinTicks = (3L * 60L);
-
-
- // -----------------------------------------------------------------
- // ctor
- //
- AEObj_pd::AEObj_pd()
- {
- }
- // -----------------------------------------------------------------
- // ctor
- //
- AEObj_pd::AEObj_pd(AEObj_pd * inParent, DescType inKind, Int_32 inIndex )
- {
- // get info from the parent object
- _AETE = inParent->_AETE;
- _AppSignature = inParent->_AppSignature;
- _ObjectSpec = inParent->_ObjectSpec;
-
- // place our object type on top of the object spec stack
- ObjectSpec_da theObjSpec;
- theObjSpec._Kind = inKind;
- theObjSpec._Pos = inIndex;
- PushObjSpec( theObjSpec );
-
- // update the formal name of this object
- {
- ostringstream theStream( ios::in | ios::out );
- theStream << GetKindName() << " " << inIndex;
- _ObjectSpec.back()._FormalName = theStream.str();
-
- }
-
- }
- // -----------------------------------------------------------------
- // ctor ... from child
- //
- AEObj_pd::AEObj_pd( AEObj_pd * inChild )
- {
- // grab the child info for ourselves
- _ObjectSpec = inChild->_ObjectSpec;
- _ObjectSpec.pop_back();
- _AETE = inChild->_AETE;
- _AppSignature = inChild->_AppSignature;
- }
-
- // -----------------------------------------------------------------
- // dtor
- //
- AEObj_pd::~AEObj_pd()
- {
- }
- // -----------------------------------------------------------------
- // Update ... this is where we manage the data coming from the app
- //
- void
- AEObj_pd::Update( ProgressProc_hi &inProgressProc, Int_32 inMaxSubModels )
- {
- // inform the user as to what is happening
- inProgressProc.BeginUpdate();
-
- // first the property values
- UpdatePropertyValues( inProgressProc );
-
- // and (if not cancelled) then we do the sub models
- if( inProgressProc.UserCancelled() == false )
- UpdateSubModelList( inProgressProc, inMaxSubModels );
-
- // finally, tell the user we are all done
- inProgressProc.EndUpdate();
- }
- // -----------------------------------------------------------------
- // UpdateSubModelList
- //
- void
- AEObj_pd::UpdateSubModelList( ProgressProc_hi &inProgressProc, Int_32 inMaxSubModels)
- {
- // grab the list of sub models from the aete
- vector<Elem_da> theSubModelTypes = (*_AETE).GetElements( GetKindID() );
-
- // and cycle thru each model type we can hold
- vector<Elem_da>::iterator theIter = theSubModelTypes.begin();
- vector<Elem_da>::iterator theLast = theSubModelTypes.end();
- Int_32 theNModels;
- while( (theIter != theLast) && (inProgressProc.UserCancelled() == false) )
- {
- // how many submodels of this kind do we have?
- theNModels = GetSubModelCount( (*theIter)._ID );
- Int_32 theMin = 1; // fudge for the application types - the finder doesn't consider itself a process
- if( GetKindID() == cComputer ) theMin = 0;
-
- for( Int_32 theIndex = theMin ; theIndex <= min(inMaxSubModels, theNModels ) ; theIndex++ ) // max out at 10 for list limit reason
- {
- AEObj_pd *theNewObj;
- // see if we are creating a regular object ... or an application object
- // ... it is awkard due to the fact that the hierarchy isn't carried throughout the os
- if( GetKindID() == cComputer )
- {
- if( theIndex != 0 ) // yet another special case (I hate what that happens)
- {
- theNewObj = new AppAEObj_pd( this, (*theIter)._ID, theIndex );
- }
- else
- {
- theNewObj = new FinderAppAEObj_pd( this, cFinderProcess, 0 );
- }
- Clone_ut<AEObj_pd> theClone( theNewObj ); // bind with a ref counter
- // inform the user
- inProgressProc.NewSubModel( theClone );
- }
- else
- {
- // the easy case ... a real object hierarchy
- theNewObj = new AEObj_pd( this, (*theIter)._ID, theIndex );
- Clone_ut<AEObj_pd> theClone( theNewObj ); //bind
- // inform the user
- inProgressProc.NewSubModel( theClone );
- }
- }
-
- ++theIter; // on to the next object kind
- }
-
- }
-
-
- // -----------------------------------------------------------------
- // GetPropertyValue
- //
- Clone_ut<PropertyValue_pd>
- AEObj_pd::GetPropertyValue( Prop_da &inProp )
- {
- // create the aegizmo string that represents the property we want
- ostringstream theStream( ios::in | ios::out );
- theStream << "'----':obj {form:prop," <<
- "want:type(prop)," <<
- "seld:type('" << As4CharString( inProp._ID ) << "')," <<
- "from:" << GetObjAddr() << "}";
-
- OSErr theErr;
- StAEDescriptor theAppleEvent;
- // use gizmos to create the apple event
- theErr = AEBuildAppleEvent( kAECoreSuite, kAEGetData,
- GetAppAddrType(),
- GetAppAddr(),
- GetSizeofAppAddr(),
- kAutoGenerateReturnID, kAnyTransactionID,
- &theAppleEvent.mDesc, theStream.str().c_str() );
- dassert( theErr == noErr );
-
- StAEDescriptor theReplyAppleEvent;
- // and off with it
- theErr = AESend( &theAppleEvent.mDesc, &theReplyAppleEvent.mDesc, kAEWaitReply,
- kAENormalPriority, _TimeoutinTicks, nil, nil );
-
- // now see what the app gave us
- StAEDescriptor *theResult = new StAEDescriptor;
- Clone_ut<StAEDescriptor> theVal( theResult );
- if( theErr == noErr )
- {
- theErr = AEGetParamDesc( theReplyAppleEvent, keyDirectObject, typeWildCard, &theResult->mDesc );
- }
- // package the return value
- PropertyValue_pd *thePVal = new PropertyValue_pd( inProp._ID, theVal, inProp._Name);
- Clone_ut<PropertyValue_pd> theRetVal( thePVal );
- return theRetVal;
- }
-
- // -----------------------------------------------------------------
- // GetName
- //
- string
- AEObj_pd::GetName()
- {
- // quick exit check ... is this a bozo aete?
- if( IsValidAETE() == false ) return string("xxx");
-
-
- // our name starts with the formal name (e.g. Document # 1)
- ostringstream theStream( ios::in | ios::out );
- theStream << GetKindName() << " # " << _ObjectSpec.back()._Pos ;
-
- // next check and see if we have a name property
- vector<Prop_da> theProps = (*_AETE).GetProperties( _ObjectSpec.back()._Kind );
- Prop_da thePropWeWant;
- thePropWeWant._ID = pName;
- vector<Prop_da>::iterator theFoundItem = find( theProps.begin(), theProps.end(), thePropWeWant );
-
- // ok, we found it ... ask the app what it is
- if( theFoundItem != theProps.end() )
- {
- Clone_ut<PropertyValue_pd> theNamePropertyValue = GetPropertyValue( Prop_da(pName) );
- _ObjectSpec.back()._Name = Asstring( *theNamePropertyValue );
- theStream << string(" (") << _ObjectSpec.back()._Name << string(")");
-
- }
- // and package up the return value
- return theStream.str();
- }
- // -----------------------------------------------------------------
- // GetKindName ... return the class name of this object
- //
- string
- AEObj_pd::GetKindName()
- {
- return (*_AETE).GetClassName( _ObjectSpec.back()._Kind );
- }
- // -----------------------------------------------------------------
- // GetKindID ... return the class id of this object
- //
- DescType
- AEObj_pd::GetKindID()
- {
- return _ObjectSpec.back()._Kind;
- }
- // -----------------------------------------------------------------
- // GetPosition
- //
- Int_32
- AEObj_pd::GetPosition()
- {
- return _ObjectSpec.back()._Pos;
- }
- // -----------------------------------------------------------------
- // GetParent ... when your walking up the hierarchy
- //
- Clone_ut< AEObj_pd >
- AEObj_pd::GetParent()
- {
- Clone_ut<AEObj_pd> theRetVal;
-
- dassert( _ObjectSpec.size() > 2 ); // check legality
- AEObj_pd *theObj = nil;
-
- // see if our parent should be an application
- if( _ObjectSpec[_ObjectSpec.size()-2]._Kind == cFinderProcess )
- {
- theObj = new AppAEObj_pd( this );
- }
- else
- { // ahhh ... the easy case
- theObj = new AEObj_pd( this );
-
- }
- dassert( theObj != nil ); // just checking
- // package up the return value
- theRetVal = Clone_ut<AEObj_pd>( theObj );
- return theRetVal;
- }
- // -----------------------------------------------------------------
- // GetSibling .. great for getting the object to your left or right
- //
- Clone_ut< AEObj_pd >
- AEObj_pd::GetSibling( Int_32 inPositionDelta )
- {
- // first get the parent that we share
- Clone_ut< AEObj_pd > theParent;
- theParent = GetParent();
- AEObj_pd * theSibling;
-
- // now see what kind of children that parent can have (remember, no one has ugly children!)
- if( (*theParent).GetKindID() == cComputer )
- {
- if( (GetPosition() + inPositionDelta ) != 0 ) // special case for the finder/apps
- {
- theSibling = new AppAEObj_pd( &(*theParent), cFinderProcess, GetPosition() + inPositionDelta );
- }
- else
- {
- theSibling = new FinderAppAEObj_pd( &(*theParent), cFinderProcess, 0 );
- }
- }
- else
- { // the easy case
- theSibling = new AEObj_pd( &(*theParent), GetKindID(), GetPosition() + inPositionDelta );
- }
- theSibling->GetName(); // update name for object label
-
-
- // package up the return value
- Clone_ut< AEObj_pd > theSiblingReturnValue( theSibling );
- return theSiblingReturnValue;
- }
- // -----------------------------------------------------------------
- // GetSubModelCount - ask the app how many
- //
- Int_32
- AEObj_pd::GetSubModelCount(DescType inModelKind)
- {
- // create the aegizmo string that represents the kind we want to count
- ostringstream theStream( ios::in | ios::out );
- theStream << "'----':" << GetObjAddr();
- theStream << ", kocl:type(" << As4CharString(inModelKind) << ")";
-
- // use gizmos to create the apple event
- OSErr theErr;
- StAEDescriptor theAppleEvent;
- theErr = AEBuildAppleEvent( kAECoreSuite, kAECountElements,
- GetAppAddrType(),
- GetAppAddr(),
- GetSizeofAppAddr(),
- kAutoGenerateReturnID, kAnyTransactionID,
- &theAppleEvent.mDesc, theStream.str().c_str() );
- dassert( theErr == noErr );
-
- // and off with it
- StAEDescriptor theReplyAppleEvent;
- theErr = AESend( &theAppleEvent.mDesc, &theReplyAppleEvent.mDesc, kAEWaitReply,
- kAENormalPriority, _TimeoutinTicks, nil, nil );
-
- // package up the return value
- Int_32 theRetVal = 0;
- if( theErr == noErr )
- {
- StAEDescriptor theResult;
- theErr = AEGetParamDesc( theReplyAppleEvent, keyDirectObject, typeLongInteger, &theResult.mDesc );
- if( theErr == noErr )
- {
- theRetVal = AsInt32( theResult.mDesc );
- }
- }
- return theRetVal;
- }
-
- // -----------------------------------------------------------------
- // UpdatePropertyValues
- //
- void
- AEObj_pd::UpdatePropertyValues( ProgressProc_hi &inProgressProc , DescType inPropertyID )
- {
- // get the list of properties associated with this class
- vector<Prop_da> theProps = (*_AETE).GetProperties( GetKindID() );
-
- // and ask the app for each one
- vector<Prop_da>::iterator theIter = theProps.begin();
- vector<Prop_da>::iterator theLast = theProps.end();
- while( (theIter != theLast) && (inProgressProc.UserCancelled() == false) )
- {
- Clone_ut<PropertyValue_pd> thePropertyValue = GetPropertyValue( *theIter );
- inProgressProc.NewPropertyValue( thePropertyValue );
- ++theIter;
- }
- }
- // -----------------------------------------------------------------
- // GetAETE
- //
- Clone_ut< AETE_da >
- AEObj_pd::GetAETE()
- {
- return _AETE;
- }
- // -----------------------------------------------------------------
- // GetObjAddr ... as a gizmo string
- //
- string
- AEObj_pd::GetObjAddr( )
- {
- // start at the top of the stack
- vector<ObjectSpec_da>::iterator theIter = _ObjectSpec.end();
-
- if( _ObjectSpec.back()._Kind == typeNull ) return string("'null'()");
-
- theIter--; // and work your way back up to the top (application)
- return GetObjAddrR( theIter );
-
- }
- // -----------------------------------------------------------------
- // GetObjAddrR
- //
- string
- AEObj_pd::GetObjAddrR( vector<ObjectSpec_da>::iterator &ioIter )
- {
- string theRetVal;
- // recurse to build a gizmo string - see the gizmo docs for the details
- if( ioIter->_Kind == cFinderProcess )
- {
- theRetVal = string("'null'()");
- }
- else
- {
- ostringstream theStream;
- theStream << "obj {form:indx,want:type('" << As4CharString( ioIter->_Kind ) + "')" +
- ",seld:" << ioIter->_Pos <<
- ",from:";
- --ioIter;
- theStream << GetObjAddrR( ioIter ) + "}";
- theRetVal = theStream.str();
- }
- return theRetVal;
- }
- // -----------------------------------------------------------------
- // GetAppAddr
- //
- void *
- AEObj_pd::GetAppAddr()
- {
- return &_AppSignature;
- }
- // -----------------------------------------------------------------
- // GetAppAddrType
- //
- OSType
- AEObj_pd::GetAppAddrType()
- {
- return typeApplSignature;
- }
- // -----------------------------------------------------------------
- // GetSizeofAppAddr
- //
- Int_32
- AEObj_pd::GetSizeofAppAddr()
- {
- return sizeof(OSType);
- }
- // -----------------------------------------------------------------
- // PushObjSpec ... you never know when your going to change a container
- //
- void
- AEObj_pd::PushObjSpec( ObjectSpec_da &inObjSpec )
- {
- _ObjectSpec.push_back( inObjSpec );
- }
- // -----------------------------------------------------------------
- // IsValidAETE
- //
- Boolean
- AEObj_pd::IsValidAETE()
- {
- return !(_AETE.Isnil() );
- }
-
-
- // -----------------------------------------------------------------
- // GetFullName ... this is the formal name (e.g. Document #1) and any real name (e.g. "xyz") concatenated
- //
- string
- AEObj_pd::GetFullName()
- {
- vector<ObjectSpec_da>::iterator theIter = _ObjectSpec.end();
- vector<ObjectSpec_da>::iterator theFirst = _ObjectSpec.begin();
-
- string theRetVal;
- do {
- theIter--;
-
- theRetVal += theIter->_FormalName;
- if( theIter->_Name.length() != 0 )
- {
- theRetVal += string(" (") + theIter->_Name + string(")");
- }
-
- // only place the 'of' if it makes sense
- if( theIter != theFirst )
- {
- theRetVal = theRetVal + " of ";
- }
- } while( theFirst != theIter );
-
- return theRetVal;
-
- }
-